#!/usr/bin/env python

import re
import sqlalchemy as sa

from model import DeclarativeBase

__all__ = ['Host']


class Host(DeclarativeBase):
    """
    Represents booru web.

    Attributes:
        - id: An integer represent the primary key.
        - name: A string represent name of booru.
        - url: A string represent the home url.
        - username: A string of username.
        - password: A string of hashed password.
        - api_key: A string to access the API.
        - hash_format: A string define the format for password.
        - type: A string indicating booru type.

            Valid value is:
                - danbooru
                - gelbooru
                - moebooru
        - status: A string determine the livelihood of the site. If status is
            Dead the host will be ignored when updating post or downloading
            image.

            Valid value is:
                - Active
                - Dead
        - route: A string for post rest resource. Moebooru using post whereas
            danbooru using posts (notice the s). This field is ignored for
            gelbooru
    """

    __tablename__ = 'hosts'

    TYPE_DANBOORU = 'Danbooru'
    TYPE_GELBOORU = 'Gelbooru'
    TYPE_MOEBOORU = 'Moebooru'

    STATUS_ACTIVE = 'Active'
    STATUS_DEAD = 'Dead'

    id = sa.Column(sa.Integer, primary_key=True)
    """
    The primary key.

    @type: int
    """

    name = sa.Column(sa.String(32), nullable=False, unique=True, index=True)
    """
    The name of booru site.

    @type: str
    """

    url = sa.Column(sa.String(32), nullable=False, unique=True, index=True)
    """
    The url of booru site.

    @type: str
    """

    username = sa.Column(sa.String(32))
    """
    The username to login.

    @type: str
    """

    password = sa.Column(sa.String(40))
    """
    The associated password in md5 format.

    @type: str
    """

    api_key = sa.Column(sa.String(40))
    """
    The key to access the API.

    @type: str
    """

    hash_format = sa.Column(sa.String(64))
    """
    The format to hash the password.

    @type: str
    """

    type = sa.Column(sa.String(8))
    """
    The type of booru site.

    Valid value is:
        - danbooru
        - gelbooru
        - moebooru

    @type: str
    """

    status = sa.Column(sa.String(6))
    """
    The livelihood of booru site.

    Valid value is:
        - Active
        - Dead

    @type: str
    """

    route = sa.Column(sa.String(8))
    """
    The route to post rest resource.

    @type: str
    """

    def create_url(self, page, tag, schema='json'):
        """
        Create url to fetch post data.

        For more information read
        U{danbooru or moebooru<https://yande.re/help/api>}
        or
        U{gelbooru<http://gelbooru.com/index.php?page=help&topic=dapi>}

        @param page: page of post to retrieve.
        @type page: int
        @param tag: tag of post to retrieve.
        @type tag: str
        @param schema: data format to download. json or xml. Default to json.
        @type schema: str

        @return: A string of url to fetch post data.
        @rtype: str
        """

        tag = re.sub(' ', '+', tag)
        if self.type == self.TYPE_GELBOORU:
            address = '%s/index.php' % self.url
            params = {'page': 'dapi', 's': 'post', 'q': 'index', 'limit': 100,
                      'tags': tag, 'pid': page - 1}
        else:
            address = '%s/%s.%s' % (self.url, self.route, schema)
            params = {'limit': 100, 'tags': tag, 'page': page}

            if self.username:
                should_login = True
                if self.api_key:
                    params['api_key'] = self.api_key
                elif self.password:
                    params['password_hash'] = self.password
                else:
                    should_login = False

                if should_login:
                    params['login'] = self.username

        param = '&'.join(['%s=%s' % (key, params[key]) for key in params])
        return '%s?%s' % (address, param)
